.code32
.text

.set kdata_sel, 	0x10
.set udata_sel,		0x2B

.macro EOI
movb $0x20,%al
outb %al,$0x20
.endm

.macro kseg_sel_restore
		movl $kdata_sel, %eax
		movw %ax, %ds
		movw %ax, %es
		movw %ax, %gs
		movw %ax, %fs
.endm

.macro useg_sel_restore
		movl $udata_sel, %eax
		movw %ax, %ds
		movw %ax, %es
		movw %ax, %gs
		movw %ax, %fs
.endm

/* save the context in process in user space */
.macro ureg_save
		 movl %ebx, -4(%ebp)
		 movl %ecx, -8(%ebp)
		 movl %edx, -12(%ebp)
		 movl %edi, -16(%ebp)
		 movl %esi, -20(%ebp)
		 movl %ebp, -24(%ebp)	
.endm	

/* restore the context of process in user space */	 
.macro ureg_restore
		movl -4(%ebp), %ebx
		movl -8(%ebp), %ecx
		movl -12(%ebp), %edx
		movl -16(%ebp), %edi
		movl -20(%ebp), %esi
		movl -24(%ebp), %ebp
.endm



#
# prototype :int divide_err(void);
#
.globl divide_err
.extern do_divide_err
divide_err:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_divide_err
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int debug_err(void);
#
.globl debug_err
.extern do_debug_err
debug_err:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_debug_err
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret

#
# prototype :int nmi(void);
#
.globl nmi
.extern do_nmi
nmi:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_nmi
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
				
#
# prototype :int breakpoint(void);
#
.globl breakpoint
.extern do_breakpoint
breakpoint:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_breakpoint
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int overflow(void);
#
.globl overflow
.extern do_overflow
overflow:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_overflow
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int boundary_err(void);
#
.globl boundary_err
.extern do_boundary_err
boundary_err:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_boundary_err
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int invalid_operation(void);
#
.globl invalid_operation
.extern do_invalid_operation
invalid_operation:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_invalid_operation
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int device_not_avail(void);
#
.globl device_not_avail
.extern do_device_not_avail
device_not_avail:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_device_not_avail
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int double_fault(void);
#
.globl double_fault
.extern do_double_fault
double_fault:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_double_fault
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int seg_overrun(void);
#
.globl seg_overrun
.extern do_seg_overrun
seg_overrun:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_seg_overrun
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int invalid_tss(void);
#
.globl invalid_tss
.extern do_invalid_tss
invalid_tss:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_invalid_tss
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int seg_not_present(void);
#
.globl seg_not_present
.extern do_seg_not_present
seg_not_present:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_seg_not_present
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int stack_fault(void);
#
.globl stack_fault
.extern do_stack_fault
stack_fault:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_stack_fault
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int general_protection(void);
#
.globl general_protection
.extern do_general_protection
general_protection:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_general_protection
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int page_fault(void);
#
.globl page_fault
.extern do_page_fault
page_fault:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_page_fault
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int float_err(void);
#
.globl float_err
.extern do_float_err
float_err:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_float_err
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int alignment_check(void);
#
.globl alignment_check
.extern do_alignment_check
alignment_check:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_alignment_check
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int machine_check(void);
#
.globl machine_check
.extern do_machine_check
machine_check:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_machine_check
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int simd_exception(void);
#
.globl simd_exception
.extern do_simd_exception
simd_exception:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_simd_exception
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int clock(void);
#
.globl clock
.extern do_clock
clock:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_clock
		
		useg_sel_restore
		ureg_restore
		
		EOI
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int keyboard(void);
#
.globl keyboard
.extern do_keyboard
keyboard:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_keyboard
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret
		
#
# prototype :int serial(void);
#
.globl serial
.extern do_serial
serial:
		pushl %ebp
		movl %esp, %ebp
		
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_serial
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret

#
# prototype :int ipc(void);
#
.globl ipc
.extern do_ipc
ipc:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_ipc
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret

#
# prototype :int syscall(void);
#
.globl syscall
.extern do_syscall
syscall:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl %eax, (%esp)
		call do_syscall
		
		useg_sel_restore
		ureg_restore
		
		movl %ebp, %esp
		popl %ebp
		iret

.code32
.globl user_test
.extern kputc,kputs,kprintf
user_msg:	.asciz "now in user test\n"
user_test:
		pushl %ebp
		movl %esp, %ebp
		subl $0x20,%esp
		
		ureg_save
		kseg_sel_restore
		
		movl $user_msg,(%esp)
		call kprintf
		
		useg_sel_restore
		ureg_restore
		
_forever:
		jmp _forever
		movl %ebp,%esp
		popl %ebp
		iret
		#jmp _forever
			
# EOF

